package study.itwill.team5.board;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import org.apache.log4j.Logger;

import study.itwill.common.DBHandler;
import study.itwill.common.DateTime;

/**
 * 덧글 - 추가, 수정, 삭제, 조회, 리스트(검색) 기능을 가진 클래스
 */
public class Comment {
	
	// Logger 클래스의 인스턴스를 받아온다.
	static Logger logger = Logger.getLogger(Comment.class);
		
	private static final String TABLE = "comment";
	
	// 데이터베이스 제어 객체에 대한 참조
	DBHandler db = null;
	
	/** 현재시간 데이터 저장을 위한 SQL구문 작성 */
	String datetime = DateTime.getInstance().getNowDateTimeString();
	
	public Comment() {
		// DB객체에 대한 참조 연결
		db = DBHandler.getInstance();
	}
	
	
	/**
	 * 덧글 작성을 위한 기능
	 * @param comment		- 덧글내용
	 * @param board_seq		- 덧글이 참조하는 게시글 일련번호
	 * @param member_seq	- 덧글이 참조하는 회원 일련번호
	 * @return int			- 추가된 덧글에 대한 일련번호를 리턴
	 */
	public int addComment(String comment, int board_seq, int member_seq) {
		//-----------------------------------------
		// 메서드 시작
		//-----------------------------------------
		logger.debug("=============== method start >> addComment");
		logger.debug("[PARAMS] comment=" + comment);
		logger.debug("[PARAMS] board_seq=" + board_seq);
		logger.debug("[PARAMS] member_seq=" + member_seq);
		
		int seq = -1;
		
		// SQL 인젝션 방어
		comment = comment.replace("'", "\'");
		
		// 트랜젝션에 대한 판단이 잘 서지 않는다면, 무조건 하면 된다.
		db.beginTrans();
		
		// INSERT 처리를 위한 구현
		String sql = "INSERT INTO comment("
	            + "comment, reg_date, edit_date, board_seq, member_seq"
	            + ") VALUES ('%s', '%s', '%s', %d, %d);";
		
		boolean result = db.execSql(sql, comment, datetime, datetime, board_seq, member_seq);
		
		//-----------------------------------------
		// 결과처리
		//-----------------------------------------
		if(result) {
			db.commit();
			seq = db.getMax(TABLE, "seq", null);
			logger.debug("처리결과 >> " + seq + "번 덧글 등록 성공");
		} else {
			db.rollback();
			logger.error("처리결과 >> 덧글 추가 실패");
		}
		
		logger.debug("=============== method end >> addComment");
		
		return seq;
	}
	
	/**
	 * 덧글 수정을 위한 기능
	 * @param seq			- 덧글 일련번호
	 * @param comment		- 덧글 내용
	 * @param board_seq		- 덧글이 참조하는 게시글 일련번호
	 * @param member_seq	- 덧글이 참조하는 회원 일련번호
	 * @return boolean		- true - 덧글수정 성공 / false - 덧글수정 실패
	 */
	public boolean editComment(int seq, String comment, int board_seq, int member_seq) {
		logger.debug("=============== method start >> editComment");
		logger.debug("[PARAMS] seq=" + seq);
		logger.debug("[PARAMS] comment=" + comment);
		logger.debug("[PARAMS] board_seq=" + board_seq);
		logger.debug("[PARAMS] member_seq=" + member_seq);
		
		// SQL 인젝션 방어
		comment = comment.replace("'", "\'");
		
		boolean result = false;
		
		db.beginTrans();
		
		String sql = "UPDATE comment "
				+ "SET comment = '%s', edit_date = '%s', board_seq = %d, member_seq = %d "
				+ "WHERE seq = %d;";
		
		result = db.execSql(sql, comment, datetime, board_seq, member_seq, seq);
		
		if(result) {
			db.commit();
			logger.debug("처리결과 >> " + seq + "번 덧글 수정성공");
		} else {
			db.rollback();
			logger.error("처리결과 >> 데이터 수정 실패 ");
		}
		
		logger.debug("=============== method end >> editComment");
		
		return result;
	}
	
	/**
	 * 덧글 삭제를 위한 기능
	 * @param seq		- 덧글 일련번호
	 * @return boolean	- true - 덧글삭제 성공 / false - 덧글삭제 실패
	 */
	public boolean deleteComment(int seq) {
		logger.debug("=============== method start >> deleteComment");
		logger.debug("[PARAMS] seq=" + seq);
		
		boolean result = false;
		
		db.beginTrans();
		
		String sql = "DELETE FROM comment WHERE seq = %d;";
		result = db.execSql(sql, seq);
		
		if(result) {
			db.commit();
			logger.debug("처리결과 >> " + seq + "번 덧글 삭제 성공");
		} else {
			db.rollback();
			logger.error("처리결과 >> 데이터 삭제 실패 ");
		}
		
		logger.debug("=============== method end >> deleteComment");
		
		return result;
	}
	
	/**
	 * 덧글 조회를 위한 기능
	 * @param seq				- 덧글 일련번호
	 * @return CommentItem		- 덧글 한개의 정보를 객체로 리턴
	 */
	public CommentItem viewComment(int seq) {
		logger.debug("=============== method start >> viewComment");
		logger.debug("[PARAMS] seq=" + seq);
		
		CommentItem item = null;
		
		// 데이터 조회
		String sql = "SELECT comment.seq, comment, comment.reg_date, comment.edit_date, board_seq, title, comment.member_seq, user_name "
				+ "FROM comment INNER JOIN board ON comment.board_seq = board.seq "
				+ "INNER JOIN member ON comment.member_seq = member.seq "
				+ "WHERE comment.seq = %d;";
		
		ResultSet rs = db.getResult(sql, seq);
		
		if(rs != null) {
			// 데이터 조회 결과 있는 경우
			try {
				rs.next();
				
				// 1) ResultSet의 모든 데이터를 변수로 추출
				int comment_seq = rs.getInt(1);
				String comment = rs.getString(2);
				String reg_date = rs.getString(3);
				String edit_date = rs.getString(4);
				int board_seq = rs.getInt(5);
				String title = rs.getString(6);
				int member_seq = rs.getInt(7);
				String user_name = rs.getString(8);
				
				// 2) 추출된 값을 객체로 구성
				item = new CommentItem(comment_seq, comment, reg_date, edit_date, board_seq, title, member_seq, user_name);
				
			} catch (SQLException e) {
				logger.error(e);
			} finally {
				// 3) 데이터 조회에 대한 메모리 반납
				try {
					rs.close();
				} catch (SQLException e) {}
				rs = null;
			}
		}
		
		if(item == null) {
			logger.error("데이터 조회 실패");
		} else {
			logger.debug("데이터 조회 성공");
			logger.debug(item.toString());
		}
				
		logger.debug("=============== method end >> viewComment");
		
		return item;
	}
	
	/**
	 * 덧글 리스트 조회를 위한 기능
	 * @param choice					- 검색조건 (0:덧글전체, 1:게시글 일련번호, 2:내용, 3:게시글 제목, 4:회원)
	 * @param search					- 검색어
	 * @return ArrayList<CommentItem>	- 덧글 전체 리스트 정보를 객체배열로 리턴
	 */
	public ArrayList<CommentItem> listComment(int choice, String search) {
		logger.debug("=============== method start >> listBoard");
		logger.debug("[PARAMS] choice=" + choice);
		logger.debug("[PARAMS] search=" + search);
		
		ArrayList<CommentItem> list = null;
		
		String sql = null;
		
		/*
		 *  덧글 검색을 위한 파라미터 정의
		 *  0, null : 덧글 전체리스트 검색
		 *  		(전체리스트 검색은 오버로딩 정의로 숫자값 하나만을 파라미터로 받을수 있다)
		 *  1, 게시글 일련번호 검색
		 *  2, "내용 검색"
		 *  3, "게시글 제목 검색"
		 *  4, "회원 검색"
		 */
		switch(choice) {
		case 0:
			sql = "SELECT comment.seq, comment, comment.reg_date, comment.edit_date, board_seq, title, comment.member_seq, user_name "
					+ "FROM comment INNER JOIN board ON comment.board_seq = board.seq "
					+ "INNER JOIN member ON comment.member_seq = member.seq "
					+ "ORDER BY comment.seq;";
			break;
			
		case 1:
			sql = "SELECT comment.seq, comment, comment.reg_date, comment.edit_date, board_seq, title, comment.member_seq, user_name "
					+ "FROM comment INNER JOIN board ON comment.board_seq = board.seq "
					+ "INNER JOIN member ON comment.member_seq = member.seq "
					+ "WHERE board_seq =" + search + " "
					+ "ORDER BY comment.seq;";
			break;
			
		case 2:
			sql = "SELECT comment.seq, comment, comment.reg_date, comment.edit_date, board_seq, title, comment.member_seq, user_name "
					+ "FROM comment INNER JOIN board ON comment.board_seq = board.seq "
					+ "INNER JOIN member ON comment.member_seq = member.seq "
					+ "WHERE comment like '%%" + search + "%%' ;";
			break;
		
		case 3:
			sql = "SELECT comment.seq, comment, comment.reg_date, comment.edit_date, board_seq, title, comment.member_seq, user_name "
					+ "FROM comment INNER JOIN board ON comment.board_seq = board.seq "
					+ "INNER JOIN member ON comment.member_seq = member.seq "
					+ "WHERE title like '%%" + search + "%%';";
			break;
			
		case 4:
			sql = "SELECT comment.seq, comment, comment.reg_date, comment.edit_date, board_seq, title, comment.member_seq, user_name "
					+ "FROM comment INNER JOIN board ON comment.board_seq = board.seq "
					+ "INNER JOIN member ON comment.member_seq = member.seq "
					+ "WHERE user_name like '%%" + search + "%%';";
			break;
			
		default:
			System.out.println("검색조건 선택이 올바르지 않습니다.");
			sql = "SELECT comment.seq, comment, comment.reg_date, comment.edit_date, board_seq, title, comment.member_seq, user_name "
					+ "FROM comment INNER JOIN board ON comment.board_seq = board.seq "
					+ "INNER JOIN member ON comment.member_seq = member.seq "
					+ "WHERE board.seq=-1;";
			break;
		}
			
		ResultSet rs = db.getResult(sql);
		
		if(rs != null) {
			// 데이터 조회 결과 있는 경우
			try {
				list = new ArrayList<CommentItem>();
				
				while(rs.next()) {
					
					// 1) ResultSet의 모든 데이터를 변수로 추출
					int comment_seq = rs.getInt(1);
					String comment = rs.getString(2);
					String reg_date = rs.getString(3);
					String edit_date = rs.getString(4);
					int board_seq = rs.getInt(5);
					String title = rs.getString(6);
					int member_seq = rs.getInt(7);
					String user_name = rs.getString(8);
					
					// 2) 추출된 값을 객체로 구성
					CommentItem item = new CommentItem(comment_seq, comment, reg_date, edit_date, board_seq, title, member_seq, user_name);
					
					// 3) ArrayList에 추가
					list.add(item);
				}
			} catch (SQLException e) {
				logger.error(e);
			} finally {
				// 4) 데이터 조회에 대한 메모리 반납
				try {
					rs.close();
				} catch (SQLException e) {}
				rs = null;
			}
		}
		
		if(list == null) {
			logger.error("덧글 조회 실패");
		} else {
			logger.debug("덧글 조회 성공 >> " + list.size() + "건 조회됨");
		}
		
		logger.debug("=============== method end >> listBoard");
		
		return list;
	}
	
	/**
	 * 덧글 전체리스트 검색을 위한 오버로딩 정의
	 * @param choice					- 0으로 파라미터를 받을시 전체리스트 조회
	 * @return ArrayList<CommentItem>	- 0과 null을 오버로딩된 메서드로 반환
	 */
	public ArrayList<CommentItem> listComment(int choice) {
		return listComment(choice, null);
	}
}
